﻿using System;
using System.ComponentModel;
using System.Collections.Generic;
using System.Diagnostics;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Shapes;
using System.Collections.ObjectModel;
using Scoreloop.CoreSocial.API;
using Scoreloop.CoreSocial.API.Model;

using System.Linq;

namespace MemoBoss
{
    public class ScoreViewModel : INotifyPropertyChanged
    {
        public ScoreViewModel()
        {
            this.Items = new ObservableCollection<ScoreItemViewModel>();
        }

        /// <summary>
        /// A collection for ItemViewModel objects.
        /// </summary>
        public ObservableCollection<ScoreItemViewModel> Items { get; private set; }

        private bool _isDataLoaded = false;
        /// <summary>
        /// Sample ViewModel property; this property is used in the view to display its value using a Binding
        /// </summary>
        /// <returns></returns>
        public bool IsDataLoaded
        {
            get
            {
                return _isDataLoaded;
            }
            set
            {
                if (value != _isDataLoaded)
                {
                    _isDataLoaded = value;
                    NotifyPropertyChanged("IsDataLoaded");
                }
            }
        }

        private string _loadingText = "Loading scores...";
        /// <summary>
        /// Sample ViewModel property; this property is used in the view to display its value using a Binding
        /// </summary>
        /// <returns></returns>
        public string LoadingText
        {
            get
            {
                return _loadingText;
            }
            set
            {
                if (value != _loadingText)
                {
                    _loadingText = value;
                    NotifyPropertyChanged("LoadingText");
                }
            }
        }

        //public bool IsDataLoaded
        //{
        //    get;
        //    private set;
        //}
        public enum SearchMode
        {
            ScoreBoards = 0,
            GameHighScore = 1,
            UserNearbyScores = 2
        }
        SearchMode searchMode;
        Action<int> UpdateScoreCallback;
        /// <summary>
        /// Creates and adds a few ItemViewModel objects into the Items collection.
        /// </summary>
        public void LoadGameScores(Score scor, Action<int> callback)
        {
            searchMode = SearchMode.GameHighScore;
            UpdateScoreCallback = callback;
            this.LoadingText = "Loading scores...";
            this.IsDataLoaded = false;
            CreateScoresControllerIfNeeded();
            if (_scoresController.IsProcessing)
                return;
            //int mode = 0;
            //switch (difficulty)
            //{
            //    case DifficultyLevel.Easy:
            //        mode = 0;
            //        break;
            //    case DifficultyLevel.Medium:
            //        mode = 1;
            //        break;
            //    case DifficultyLevel.Hard:
            //        mode = 2;
            //        break;
            //    case DifficultyLevel.MemoBoss:
            //        mode = 3;
            //        break;
            //}

            //_scoresController.LoadScores(_scoresController.GlobalSearchList, new Range(0, 25), mode);
            _scoresController.LoadScores(_scoresController.GlobalSearchList, _scoresController.User, 25, scor.Mode);

        }
        public void LoadScoreBoard(DifficultyLevel difficulty)
        {
            searchMode = SearchMode.ScoreBoards;
            UpdateScoreCallback = null;
            this.LoadingText = "Loading scores...";
            this.IsDataLoaded = false;
            CreateScoresControllerIfNeeded();
            if (_scoresController.IsProcessing)
                return;
            int mode = 0;
            switch (difficulty)
            {
                case DifficultyLevel.Easy:
                    mode = 0;
                    break;
                case DifficultyLevel.Medium:
                    mode = 1;
                    break;
                case DifficultyLevel.Hard:
                    mode = 2;
                    break;
                case DifficultyLevel.MemoBoss:
                    mode = 3;
                    break;
            }

            _scoresController.LoadScores(_scoresController.GlobalSearchList, new Range(0, 25), mode);
            //_scoresController.LoadScores(_scoresController.GlobalSearchList, _scoresController.User, 25, mode);
            
        }
        public IScoresController _scoresController;

        void CreateScoresControllerIfNeeded()
        {
            if (_scoresController == null)
            {
                _scoresController = App.slClient.CreateScoresController();
                _scoresController.RequestFailed += ScoresController_RequestFailed;
                _scoresController.RequestCancelled += ScoresController_RequestFailed;
                _scoresController.ScoresLoaded += ScoresController_ScoresLoaded;
            }
        }
        public void EnsureProcessing() 
        {
            if (_scoresController.IsProcessing) 
            {
                _scoresController.LoadScores(_scoresController.GlobalSearchList, _scoresController.User, 25, _scoresController.Mode);
            }
        }

        void ScoresController_RequestFailed(object sender, RequestControllerEventArgs<IRequestController> e)
        {
            //MessageBox.Show(e.Error.ToString());
            this.LoadingText = "Unable to connect...";
        }

        void ScoresController_ScoresLoaded(object sender, RequestControllerEventArgs<IScoresController> e)
        {
            if (UpdateScoreCallback != null)
            {
                var sc = _scoresController.Scores.Where(x => x.User == App.slClient.Session.User).First();
                if (ScoreHelper.GetHighScore(_scoresController.Mode) < sc.Result)
                {
                    ScoreHelper.SaveHighScore(_scoresController.Mode, (int)sc.Result);
                    UpdateScoreCallback((int)sc.Result);
                }
            }
            if (searchMode == SearchMode.UserNearbyScores && _scoresController.Scores.Count()>0) 
            {
                this.Items.Add(new ScoreItemViewModel()
                {
                    Number = Items.Last().Number + 1,
                    Rank = null,
                    User = null,
                    Score = null,
                    Level = null,
                    Color = (Items.Last().Number + 1) % 2
                });
            }

            int i = 0;
            foreach (Score scor in _scoresController.Scores)
            {i++;
                this.Items.Add(new ScoreItemViewModel()
                {
                    Number = i,
                    Rank = (int)scor.Rank,
                    User = scor.User.Login,
                    Score = (int)scor.Result,
                    Level = scor.Level,
                    Color = scor.User == App.slClient.Session.User ? 2 : i % 2
                });

            }
            var tst = _scoresController.Scores.Where(x => x.User == App.slClient.Session.User);
            if (searchMode == SearchMode.ScoreBoards && _scoresController.Scores.Where(x => x.User == App.slClient.Session.User).Count() == 0)
            {
                searchMode = SearchMode.UserNearbyScores;
              
                _scoresController.LoadScores(_scoresController.GlobalSearchList, _scoresController.User, 10, _scoresController.Mode);

            }
            else
            {
                this.IsDataLoaded = true;
            }
        }

        public event PropertyChangedEventHandler PropertyChanged;
        private void NotifyPropertyChanged(String propertyName)
        {
            PropertyChangedEventHandler handler = PropertyChanged;
            if (null != handler)
            {
                handler(this, new PropertyChangedEventArgs(propertyName));
            }
        }
    }
}